#pragma once
#include "globals.h"

class Graphics
{
public:
	static const int TEXT_SIZE = 1024;
	/** colors */
	static const int
		DEFAULT,
		RED,
		GREEN,
		BLUE,
		INTENSITY,
		BLACK,
		DARK_GRAY,
		GRAY,
		WHITE,
		BACK_RED,
		BACK_GREEN,
		BACK_BLUE,
		BACK_INTENSITY,
		BACK_GRAY;

	char TEXT[TEXT_SIZE];
private:
	char * buffer;
	unsigned char * color;

	char * lastbuffer;
	unsigned char * lastcolor;

	int width, height;
public:
	int getWidth(){return width;}
	int getHeight(){return height;}

	void clear(char a_fill, unsigned char a_color)
	{
		int total = width*height;
		for(int i = 0; i < total; ++i){
			buffer[i] = a_fill;
			color[i] = a_color;
		}
	}
	Graphics(int w, int h):width(w),height(h)
	{
		int total = width*height;
		buffer = new char[total];
		color = new unsigned char[total];
		lastbuffer = new char[total];
		lastcolor = new unsigned char[total];
	}
	~Graphics()
	{
		delete [] buffer;
		delete [] color;
		delete [] lastbuffer;
		delete [] lastcolor;
	}
	int bufferIndex(int x, int y)
	{
		if(x < 0 || x >= width
		|| y < 0 || y >= height)
			return -1;
		return x+y*width;
	}
	void setAt(int x, int y, char c, unsigned char a_color){
		int index = bufferIndex(x,y);
		if(index >= 0){
			buffer[index] = c;
			color[index] = a_color;
		}
	}
	void setAt(int x, int y, char c){
		setAt(x,y,c,DEFAULT);
	}
	void setColorAt(int x, int y, unsigned char a_color){
		int index = bufferIndex(x,y);
		if(index >= 0)
			color[index] = a_color;
	}
	char getCharAt(int x, int y){
		int index = bufferIndex(x,y);
		if(index >= 0)
			return buffer[index];
		return 0;
	}
	unsigned char getColorAt(int x, int y){
		int index = bufferIndex(x,y);
		if(index >= 0)
			return color[index];
		return 0;
	}
	void fillRect(int x, int y, int width, int height, char fill, unsigned char a_color){
		for(int row = y; row < y+height; ++row){
			for(int col = x; col < x+width; ++col){
				setAt(col, row, fill, a_color);
			}
		}
	}
	/**
	 * @param text what text to draw
	 * @param a_x rectangle x
	 * @param a_y rectangle y
	 * @param a_w rectangle width
	 * @param a_h rectangle height
	 * @param wrapping whether or not to wrap to the next line if the text goes over the edge
	 * @param a_color what color the text should be
	 */
	void drawText(char * text, int a_x, int a_y, int a_w, int a_h, bool wraping, int a_color){
		int index = 0;
		char c;
		int x = a_x;
		int y = a_y;
		while(text[index]){
			c = text[index++];
			switch(c){
			case '\t':
				for(int i = 0; i < 4; ++i){
					setAt(x++,y,' ',a_color);
				}
				break;
			case '\b':
				--x;
				break;
			case '\r':
				x = a_x;
				break;
			case '\n':
				y++;
				x = a_x;
				break;
			default:
				setAt(x++,y,c,a_color);
				if(wraping && x >= a_x+a_w){
					y++;
					x = a_x;
				}
			}
			if(y >= a_y+a_h)
				return;
		}
	}
	void drawText(char * text, int x, int y, unsigned char a_color){
		drawText(text,x,y,width-x,height-y,false,a_color);
	}
	void drawText(char * text, int x, int y){
		drawText(text,x,y,DEFAULT);
	}
	void drawText(char * text, int x, int y, int w, int h, bool wraping){
		drawText(text,x,y,w,h,wraping,DEFAULT);
	}
	void render();

};
